package com.github.shiqiyue.app.config.security;

import com.github.shiqiyue.app.api.sapi.common.CaptchaTypeEnum;
import com.github.shiqiyue.app.api.sapi.common.SessionKeyConstants;
import com.github.shiqiyue.app.config.captcha.ICaptchaStore;
import com.github.shiqiyue.app.config.security.sapi.*;
import com.github.shiqiyue.app.modules.sys.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/***
 * 安全配置
 * @author wenyao.wu
 * @since 2020年5月1日
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MultiHttpSecurityConfiguration {


    /***
     * sapi 安全配置
     * @author wenyao.wu
     * @since 2020年5月1日
     */
    @Order(1)
    @Configuration
    public static class SapiSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Autowired
        private IUserService userService;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Autowired
        private ICaptchaStore captchaStore;


        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            // sapi 认证信息提供者
            SapiUserDetailService sapiUserDetailService = new SapiUserDetailService();
            sapiUserDetailService.setUserService(userService);
            auth.userDetailsService(sapiUserDetailService).passwordEncoder(passwordEncoder);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // 登录链接
            String loginUrl = "/sapi/sys/login/login";
            // 登出链接
            String logoutUrl = "/sapi/sys/login/logout";

            http.headers().cacheControl().disable();
            http.csrf().disable();
            http.headers().frameOptions().disable();

            SapiAuthenticationSuccessHandler sapiAuthenticationSuccessHandler = new SapiAuthenticationSuccessHandler();
            sapiAuthenticationSuccessHandler.setSessionKeyIp(SessionKeyConstants.ATTRIBUTE_IP);
            sapiAuthenticationSuccessHandler.setSessionKeyUserAgent(SessionKeyConstants.ATTRIBUTE_USER_AGENT);


            // 登录验证码过滤器
            LoginCaptchaFilter loginCaptchaFilter = new LoginCaptchaFilter();
            loginCaptchaFilter.setLoginCaptchaValidator(new LoginCaptchaFilter.LoginCaptchaValidator() {
                @Override
                public Boolean isLoginCaptchValid(String code, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
                    return captchaStore.match(code, CaptchaTypeEnum.BG_LOGIN.getValue(), true);
                }
            });
            loginCaptchaFilter.setLoginUrl(loginUrl);
            loginCaptchaFilter.setCaptchaAttributeName("captcha");

            http.antMatcher("/sapi/**")
                    // 表单登录
                    .formLogin().loginProcessingUrl(loginUrl).permitAll()
                    .successHandler(sapiAuthenticationSuccessHandler)
                    .failureHandler(new SapiAuthenticationFailureHandler())
                    .and()
                    // 添加登录验证码验证过滤器
                    .addFilterBefore(loginCaptchaFilter, UsernamePasswordAuthenticationFilter.class)
                    // 登出
                    .logout().logoutUrl(logoutUrl).permitAll()
                    // 登出成功处理
                    .logoutSuccessHandler(new SapiLogoutSuccessHandler())
                    .and()
                    .exceptionHandling()
                    // 权限不足处理
                    .accessDeniedHandler(new SapiAccessDeniedHandler())
                    // 未认证处理
                    .authenticationEntryPoint(new SapiAuthenticationEntryPoint())
                    .and()
                    // 链接权限配置
                    .authorizeRequests()
                    .antMatchers("/sapi/sys/login/**").permitAll()
                    .antMatchers("/sapi/captcha/get").permitAll()
                    .antMatchers("/sapi/**").authenticated()
                    .and();

        }


        @Override
        public void configure(WebSecurity web) throws Exception {
            super.configure(web);
        }
    }




}
